#ifndef SHAPES_H
#define SHAPES_H

#include "Vector.h"
#include "Ray.h"
#include "Point.h"
#include "Color.h"
#include "Material.h"
#include "Transform.h"

namespace GeometryPrimitives
{
	class Shape
	{
	protected:
		Shape(const Shape& s);
		Shape& operator=(const Shape& s);
		MathGraphics::Transform objToWorld;
		MathGraphics::Transform worldToObj;
		
	public:
		GraphicsColor::RGB* col;
		const LightingMaterial::Material& material;

		virtual bool intersect(const MathGraphics::Ray& ray) = 0;
		virtual MathGraphics::Vector getNormal(const MathGraphics::Vector& point) const = 0;
		Shape(const MathGraphics::Transform& objectToWorld , const LightingMaterial::Material& material) : 
				material(material)
		{
			objToWorld = objectToWorld;
			worldToObj = MathGraphics::Transform(objToWorld.inv, objToWorld.mat);
		}
	};

	class Sphere : public Shape
	{
	private:
		double radius;

	public:
		Sphere(const MathGraphics::Transform& objectToWorld, const double radius, GraphicsColor::RGB* color, const LightingMaterial::Material& material);
		bool intersect(const MathGraphics::Ray& ray);
		MathGraphics::Vector getNormal(const MathGraphics::Vector& point) const;
	};

	class PointLight : public Shape
	{
	public:

		PointLight(const MathGraphics::Transform& objectToWorld, const LightingMaterial::Material& mat) : Shape(objectToWorld, mat)
		{
		}

		bool intersect(const MathGraphics::Ray& r)
		{
			MathGraphics::Ray ray;

			worldToObj(r, &ray);
			double zi = ray.o.z;

			if (zi == 0.0)
			{
				ray.t = 0.0f;
				return true;
			}

			double ti = zi / ray.v.z;
			if (ti < 0.0)
			{
				ti *= -1;
			}
			ray.t = ti;

			//objToWorld(*ray, ray);
			return true;
		}

		MathGraphics::Vector getNormal(const MathGraphics::Vector& point) const
		{
			MathGraphics::Point pt = objToWorld(MathGraphics::Point(0, 0, 0));
			return MathGraphics::Vector(pt.x, pt.y, pt.z);
		}
	};
}
#endif